package com.yanghui.dtracing.core;

import com.yanghui.dtracing.core.classLoader.AgentClassLoader;
import com.yanghui.dtracing.core.config.AgentConfig;
import com.yanghui.dtracing.core.plugin.IClassEnhancePluginDefine;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class PluginBootstrap {

    private AgentConfig agentConfig;

    private List<PluginDefine> pluginDefineList = new ArrayList<>();

    public PluginBootstrap(){}

    public PluginBootstrap(AgentConfig agentConfig){
        this.agentConfig = agentConfig;
    }

    public List<IClassEnhancePluginDefine> loadPlugins(){
        this.load();
        List<IClassEnhancePluginDefine> resultList = new ArrayList<>();
        for(PluginDefine pluginDefine : pluginDefineList){
            try{
                Object plugin = Class.forName(pluginDefine.getClassName(),true, AgentClassLoader.getDefault()).newInstance();
                if(plugin instanceof IClassEnhancePluginDefine){
                    resultList.add((IClassEnhancePluginDefine)plugin);
                }
            }catch (Throwable t){
                t.printStackTrace();
            }
        }
        return resultList;
    }

    private void load(){
        PluginResourceResolver pluginResourceResolver = new PluginResourceResolver();
        List<URL> pluginResources = pluginResourceResolver.getPluginDefineResource();
        Set<String> set = new HashSet<>();/**去重相同的插件名称**/
        for(URL url : pluginResources){
            List<String> pluginDefines = pluginResourceResolver.getDefines(url);
            if(null == pluginDefines || pluginDefines.isEmpty()){
                continue;
            }
            for(String pluginDefineStr : pluginDefines){
                /**排除注释插件**/
                if (pluginDefineStr.trim().length() == 0 || pluginDefineStr.startsWith("#")) {
                    continue;
                }
                PluginDefine pluginDefine = PluginDefine.build(pluginDefineStr);
                if(null == pluginDefine || !set.add(pluginDefine.getName())){
                    continue;
                }
                this.pluginDefineList.add(pluginDefine);
            }
        }
        /**
         * 排除指定的插件
         */
        List<String> excludePluginList = this.agentConfig.getExcludePluginList();
        if(excludePluginList.isEmpty()){
            return;
        }
        this.pluginDefineList = this.pluginDefineList.stream().filter(item -> !excludePluginList.contains(item.getName().toLowerCase())).collect(Collectors.toList());
    }
}
